/** PatientModel */
package server.service.patient;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import server.SocketManager;
import server.service.user.UserModel;
import domain.exception.ValidationException;
import domain.patient.Patient;


/**
Talks to the PatientDao and Panels
 * @author jessienewman
 * @version $Revision: 1.0 $
 */
public class PatientModel {
	/**
	 * Field dao.
	 */
	private PatientDao dao;
	
	/**
	 * Field LOGGER.
	 */
	private static final Logger LOGGER = Logger.getLogger(SocketManager.class.getName());

	/**
	 * Constructor for PatientModel.
	 */
	public PatientModel() {
		dao = new PatientDao();
	}

	/**
	 * Method findPatients.
	 * @param s String
	
	 * @return List */
	public List<Patient> findPatients(String s) {
		return dao.findPatients(s);
	}

	/**
	 * Method getPatient.
	 * @param id Integer
	
	 * @return Patient */
	public Patient getPatient(Integer id) {
		return dao.getPatient(id);
	}

	/**
	 * Method isPatient.
	 * @param id Integer
	
	 * @return Boolean */
	public Boolean thisIsPatient(Integer id) {
		return dao.getPatient(id) != null;
	}

	/**
	 * Method addPatient.
	 * @param p Patient
	 * @param username String
	 * @param p1 String
	 * @param p2 String	
	 * @return Integer 
	 * @throws ValidationException */
	public Integer addPatient(final Patient p, String username, 
			String p1, String p2) throws ValidationException {
			UserModel um = new UserModel();
			um.assertMatchingPasswords(p1, p1);
			validatePatient(p);
			return dao.addPatient(p);
	}

	/**
	 * Method modifyName.
	 * @param id Integer
	 * @param nameFirst String
	 * @param nameMiddle String
	 * @param nameLast String
	
	 * @throws ValidationException */
	public void modifyName(Integer id, String nameFirst, 
			String nameMiddle, String nameLast) 
	throws ValidationException{
		if (!assertNotEmpty(nameFirst) ) {
			throw new ValidationException("Please include a First Name"); // $codepro.audit.disable nullPointerDereference
		}
		if (!assertNotEmpty(nameLast) ) {
			throw new ValidationException("Please include a Last Name"); // $codepro.audit.disable nullPointerDereference
		}
		dao.modifyNameFirst(id, nameFirst);
		dao.modifyNameMiddle(id, nameMiddle);
		dao.modifyNameLast(id, nameLast);
	}

	/**
	 * Method validatePatient.
	 * @param p Patient
	
	 * @throws ValidationException */
	public void validatePatient(final Patient p) throws ValidationException {
		String msg = "";
		
		/*
		if (!assertNotEmpty(p.getNameFirst())) {
			msg += "First name is empty. \n";
		}

		if (!assertNotEmpty(p.getNameLast())) {
			msg += "Last name is empty. \n";
		}

		if (!assertValidAddress(p.getAddress())) {
			msg += "Address is invalid. \n";
		}
		/*if (p.getDateOfBirth() != null && !assertValidDOB(
				p.getDateOfBirth().toString())) {
			msg += "Date of birth is invalid. \n";
		}*/

		if (!msg.isEmpty()) {
			throw new ValidationException(msg); // $codepro.audit.disable nullPointerDereference
		}

	}

	/**
	 * Method assertNotEmpty.
	 * @param name String
	
	 * @return boolean */
	public boolean assertNotEmpty(String name) { // $codepro.audit.disable booleanMethodNamingConvention
		if (name.equals("")) {
			return false;
		}
		return true;
	}

	/**
	 * Method assertValidAddress.
	 * @param address String
	
	 * @return boolean */
	public boolean assertValidAddress(String address) {  // $codepro.audit.disable booleanMethodNamingConvention -->
		return address.matches("[0-9]+ [A-Z][A-Za-z ]+.? " +
				"[A-Za-z ]+, [A-Z]{2}  ?[0-9]{5}(-[0-9]{4})?");
	}

	/**
	 * Method modifyContact.
	 * @param id Integer
	 * @param address String
	 * @param email String
	
	 * @throws ValidationException */
	public void modifyContact(Integer id, String address, 
			String email) throws ValidationException {
		if (!assertValidAddress(address)) {
			throw new ValidationException("Address is not valid"); // $codepro.audit.disable nullPointerDereference
		}
		dao.modifyAddress(id, address);
		dao.modifyEmail(id, email);
	}

	/**
	 * Method modifyInsurance.
	 * @param id Integer
	 * @param insurance String
	 */
	public void modifyInsurance(Integer id, String insurance) {
		dao.modifyInsurance(id, insurance);
	}

	/**
	 * Method modifyAllergies.
	 * @param id Integer
	 * @param allergies String
	 */
	public void modifyAllergies(Integer id, String allergies) {
		dao.modifyAllergies(id, allergies);
	}

	/**
	 * Method modifyDOB.
	 * @param id Integer
	 * @param date String
	
	 * @throws ValidationException */
	public void modifyDOB(Integer id, String date) throws ValidationException{
		//TODO: FIX THIS!
		if (date.equals("")) {
			dao.modifyDOB(id, null);
			return;
		} else if (!assertValidDOB(date)) {
			throw new ValidationException("Invalid Date"); // $codepro.audit.disable nullPointerDereference
		}
		SimpleDateFormat sdf = new SimpleDateFormat("MMMMM dd, yyyy");
		try {
			dao.modifyDOB(id, sdf.parse(date));
		} catch(Exception e) {
			LOGGER.warning(e.getMessage());
		}
	}

	/**
	 * Method assertValidDOB.
	 * @param date String
	
	 * @return boolean */
	public boolean assertValidDOB(String date){ // $codepro.audit.disable booleanMethodNamingConvention
		Date today = new Date();
		if (date.equals(today.toString())) {
			date = ""; // $codepro.audit.disable questionableAssignment
			return true;
		}
		SimpleDateFormat sdf = new SimpleDateFormat("MMMMM dd, yyyy");
		if (date.equals("")) {
			return true;
		}
		try {
			Date dob = sdf.parse(date);
			if (dob.after(new Date())) {
				return false;
			}
			return true;
		} catch(ParseException pe) {
			LOGGER.warning(pe.getMessage());
			return false;
		}
	}

	/**
	 * Method getAllPatients.
	
	 * @return Patient[] */
	public List<Patient> getAllPatients() {
		return dao.getAllPatients();
	}
	
	/**
	 * super's toString
	
	 * @return super's toString */
	public String toString() {
		return super.toString();
	}
}
